#!/bin/bash

SCRIPT=$(realpath "$0")
SCRIPTPATH=$(dirname "$SCRIPT")

if [ $EUID -ne 0 ]; then
	echo "$(basename $0) must be ran as superuser or sudo"
	exit 1
fi

while [[ $# -gt 0 ]]
do
key="$1"
case $key in
	--flavor)
	BUILD_MANIFEST="${SCRIPTPATH}/presets/$2.sh"
	BUILD_MANIFEST_ID="$2"
	POSTCOPY_DIR="$2"
	if [[ "${BUILD_MANIFEST_ID}" =~ "dev" ]]; then
		BUILD_MANIFEST_ID=$(echo $2 | cut -d '-' -f 1)
		BRANCH_OVERRIDES=$(echo $2 | cut -d '-' -f 2)
	fi
	echo "Manifest ID: ${BUILD_MANIFEST_ID}"
	shift
	shift
	;;
	--deployment_rel)
	RELEASETYPE="$2.sh"
	echo "Deployment: ${RELEASETYPE}"
	shift
	shift
	;;
	--upstream_ver)
	STEAMOS_VERSION=$2
	echo "Upstream Version: ${STEAMOS_VERSION}"
	shift
	shift
	;;
	--snapshot_ver)
	SNAPSHOTVERSION="$2"
	echo "Build version: ${SNAPSHOTVERSION}"
	shift
	shift
	;;
	--workdir)
	WORKDIR="$2/buildwork"
	echo "Working directory: ${WORKDIR}"
	shift
	shift
	;;
	--output-dir)
	if [[ -z "$2" ]]; then
		OUTPUT=${WORKDIR}
	else
		OUTPUT="$2"
		if [[ -n "${BRANCH_OVERRIDES}" ]]; then
			OUTPUT="$2/${BRANCH_OVERRIDES}"
		fi
	fi
	shift
	shift
	;;
    --add-release)
	IS_HOME_BUILD=true
	if [[ ! "${OUTPUT}" =~ "images" ]]; then
		echo "Specific output directories should be preceeded with images for release images."
		exit 255
	fi
	shift
	shift
	;;
    --rclone_path)
	RC_PATH="$2"
	shift
	shift
	;;
	--rclone_root)
	if [[ -n "${RC_PATH}" ]]; then
		RC_ROOT="$2"
	else
		echo "rclone root can be used only with --rclone_path"
		exit 255
	fi
	shift
	shift
	;;
    --donotcompress)
	NO_COMPRESS="1"
	if [[ "${IS_HOME_BUILD}" == "true" ]]; then
		echo "Decompressed images are not supported in shipping builds"
		exit 127
	fi
	shift
	shift
	;;
	*)    # unknown option
    echo "Unknown option: $1"
    exit 1
    ;;
esac
done

# Check if everything is set.
if [[ -z "{$BUILD_MANIFEST}" ]]; then
	echo "Build flavor was not set. Aborting."
	exit 0
fi
if [[ -z "${SNAPSHOTVERSION}" ]]; then
	echo "Snapshot directory was not set. Aborting."
	exit 0
fi
if [[ -z "${WORKDIR}" ]]; then
	echo "Workdir was not set. Aborting."
	exit 0
fi

if [ -n "${SNAPSHOTVERSION}" ]
then
  export RELEASE_TAG=${SNAPSHOTVERSION}
else
  export RELEASE_TAG=$(date +%Y%m%d.%H%M)
fi

source ${BUILD_MANIFEST}

ROOT_WORKDIR=${WORKDIR}/rootfs_mnt
echo "Preparing to create deployment image..."
# Pre-build cleanup
umount -l ${ROOT_WORKDIR}
if [ -d "${WORKDIR}" ]
then
	rm -rf ${WORKDIR}
fi

# Start building here
mkdir -p ${WORKDIR}

PACCFG_SOURCE="metadata/pacman.conf"
cp -f ${PACCFG_SOURCE} ${WORKDIR}
sed -i 's~@STEAMOS_VERSION@~'${STEAMOS_VERSION}'~g' ${WORKDIR}/pacman.conf
PACCFG=${WORKDIR}/pacman.conf

SF_PACCFG_SOURCE="metadata/steamfork-mirrorlist"
cp -f ${SF_PACCFG_SOURCE} ${WORKDIR}
sed -i 's~@STEAMOS_VERSION@~'${STEAMOS_VERSION}'~g' ${WORKDIR}/steamfork-mirrorlist
SF_PACCFG=${WORKDIR}/steamfork-mirrorlist

mkdir -p ${OUTPUT}
mkdir -p ${ROOT_WORKDIR}
fallocate -l 10000MB ${WORKDIR}/work.img
mkfs.btrfs ${WORKDIR}/work.img
mkdir -p ${WORKDIR}/rootfs_mnt
mount -t btrfs -o loop,compress-force=zstd:1,discard,noatime,nodiratime ${WORKDIR}/work.img ${ROOT_WORKDIR}

echo "Bootstrapping main filesystem"
# Start by bootstrapping essentials
mkdir -p ${ROOT_WORKDIR}/${OS_FS_PREFIX}_root/rootfs
mkdir -p ${ROOT_WORKDIR}/var/cache/pacman/pkg
mount --bind /var/cache/pacman/pkg/ ${ROOT_WORKDIR}/var/cache/pacman/pkg
pacstrap -C ${PACCFG} ${ROOT_WORKDIR} ${BASE_BOOTSTRAP_PKGS}
echo "Bootstrapping kernel..."
pacstrap -C ${PACCFG} ${ROOT_WORKDIR} ${KERNELCHOICE} ${KERNELCHOICE}-headers

echo "Generating fstab..."

# fstab
cat <<EOF > ${ROOT_WORKDIR}/etc/fstab
LABEL=${OS_FS_PREFIX}_root /	btrfs subvol=rootfs/${BUILDVER},compress-force=zstd:1,discard,noatime,nodiratime 0 0
LABEL=${OS_FS_PREFIX}_root /${OS_FS_PREFIX}_root	btrfs rw,compress-force=zstd:1,discard,noatime,nodiratime,nodatacow 0 0
LABEL=${OS_FS_PREFIX}_var /var	ext4 rw,relatime 0 0
LABEL=${OS_FS_PREFIX}_home /home	ext4 rw,relatime 0 0
EOF

sed -i 's/# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/g' ${ROOT_WORKDIR}/etc/sudoers

echo "Bootstrapping SteamFork core root.."
pacstrap -C ${PACCFG} ${ROOT_WORKDIR} ${UI_BOOTSTRAP}
rm ${ROOT_WORKDIR}/etc/pacman.conf
cp ${PACCFG} ${ROOT_WORKDIR}/etc/pacman.conf

if [ ! -d "${ROOT_WORKDIR}/etc/pacman.d" ]
then
  mkdir -p "${ROOT_WORKDIR}/etc/pacman.d"
fi
cp ${SF_PACCFG} ${ROOT_WORKDIR}/etc/pacman.d

if [ ! -d "${ROOT_WORKDIR}/usr/share/defaults" ]
then
  mkdir -p ${ROOT_WORKDIR}/usr/share/defaults
fi
cp ${PACCFG} ${ROOT_WORKDIR}/usr/share/defaults

RELEASE_TYPE="$(echo ${OS_CODENAME} | tr '[:upper:]' '[:lower:]')"

echo "Write os-release..."
cat <<EOF >${ROOT_WORKDIR}/etc/os-release
NAME="SteamOS"
PRETTY_NAME="SteamOS"
VERSION_CODENAME=holo
DISTRO_NAME="${DISTRO_NAME}"
ID=steamos
ID_LIKE=arch
ANSI_COLOR="1;35"
HOME_URL="${HOME_URL}"
DOCUMENTATION_URL="${DOCUMENTATION_URL}"
SUPPORT_URL="${SUPPORT_URL}"
BUG_REPORT_URL="${BUG_REPORT_URL}"
LOGO=steamos
VERSION_ID="${RELEASE_TAG}"
VARIANT_ID="${RELEASE_TYPE}"
BUILD_ID="${RELEASE_TAG}"
STEAMOS_VERSION="${STEAMOS_VERSION}"
EOF

echo "Write steamfork-release"
cat <<EOF >${ROOT_WORKDIR}/etc/steamfork-release
IMAGE_ID="${BUILDVER}"
OS_TAG=${RELEASE_TAG}
RELEASETYPE=${RELEASE_TYPE}
ISINTERNAL=no
EOF

echo -e $IMAGE_HOSTNAME > ${ROOT_WORKDIR}/etc/hostname
mkdir -p ${ROOT_WORKDIR}/etc/steamos-atomupd
cat <<EOF >${ROOT_WORKDIR}/etc/steamos-atomupd/manifest.json
{
    "product": "steamos",
    "release": "holo",
    "variant": "steamdeck",
    "arch": "amd64",
    "version": "${SNAPSHOTVERSION}",
    "buildid": "${SNAPSHOTVERSION}",
    "checkpoint": false,
    "estimated_size": 0
}
EOF

echo "Copying postcopy items..."
if [[ -d "${SCRIPTPATH}/postcopy" ]]; then
	cp -r ${SCRIPTPATH}/postcopy/* ${ROOT_WORKDIR}
fi

if [[ -n "$PLYMOUTH_THEME" ]]; then
	echo "Setting $PLYMOUTH_THEME theme for plymouth bootsplash..."
	arch-chroot ${ROOT_WORKDIR} plymouth-set-default-theme -R $PLYMOUTH_THEME
fi

for binary in ${POSTCOPY_BIN_EXECUTION}
do
	arch-chroot ${ROOT_WORKDIR} $binary && rm -rf ${ROOT_WORKDIR}/usr/bin/$binary
done

cat <<EOF > ${ROOT_WORKDIR}/usr/lib/systemd/system/var-lib-pacman.mount
[Unit]
Description= ${DISTRO_NAME} onload - /var/lib/pacman

[Mount]
What=/${OS_FS_PREFIX}_root/rootfs/${FINAL_DISTRIB_IMAGE}/var/lib/pacman
Where=/var/lib/pacman
Type=none
Options=bind

[Install]
WantedBy=steamos-offload.target
EOF

echo "Copy pacman.conf..."
cp ${PACCFG} ${ROOT_WORKDIR}/etc/

echo "Set repository path..."
sed -i 's~@RELEASE_TYPE@~${RELEASE_TYPE}~g' ${ROOT_WORKDIR}/etc/pacman.d/steamfork-mirrorlist

echo "Generating en_US.UTF-8 locale..."
sed -i 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/g' ${ROOT_WORKDIR}/etc/locale.gen
arch-chroot ${ROOT_WORKDIR} locale-gen
arch-chroot ${ROOT_WORKDIR} localectl set-locale LANG=en_US.UTF-8
arch-chroot ${ROOT_WORKDIR} mkdir -p /etc/lib/hwsupport/devicequirks

for ENABLED_SERVICE in ${ENABLED_SERVICES[@]}
do
  echo "Enable service ${ENABLED_SERVICE}"
  arch-chroot ${ROOT_WORKDIR} systemctl enable ${ENABLED_SERVICE}
done

for DISABLED_SERVICE in ${DISABLED_SERVICES[@]}
do
  echo "Disable service ${DISABLED_SERVICE}"
  arch-chroot ${ROOT_WORKDIR} systemctl disable ${DISABLED_SERVICE}
  arch-chroot ${ROOT_WORKDIR} rm -f /usr/lib/systemd/system/multi-user.target.wants/${DISABLED_SERVICE}
done

echo "Enable nopasswd sudo (req by steam and other tools)"
  arch-chroot ${ROOT_WORKDIR} sed -i 's~ALL$~NOPASSWD: ALL~g' /etc/sudoers.d/wheel

echo "Patch Audio output to add generic devices to the filter."
  arch-chroot ${ROOT_WORKDIR} sed -i '/matches = \[/a \      {\n\        node.name = "~alsa_output.*"\n\        alsa.card_name = "HD-Audio Generic"\n\      }' /usr/share/wireplumber/hardware-profiles/valve-jupiter/wireplumber.conf.d/alsa-card1.conf

echo "Fix runtime audio configuration."
  for AUDIO_SERVICE in pipewire wireplumber
  do
    arch-chroot ${ROOT_WORKDIR} sed -i 's~multi-user.target~local-fs.target~g' /usr/lib/systemd/system/${AUDIO_SERVICE}-sysconf.service
    arch-chroot ${ROOT_WORKDIR} systemctl enable ${AUDIO_SERVICE}-sysconf.service
  done

echo "Enable systemd-resolved."
rm -f ${ROOT_WORKDIR}/etc/resolv.conf
ln -sf /run/systemd/resolve/stub-resolv.conf ${ROOT_WORKDIR}/etc/resolv.conf

echo "Fix blank screen desktop issue."
  sed -i '/cd "$config_dir"/a \ \ \ \ rm -rf /tmp/.ICE-unix' /usr/bin/startplasma-steamos-oneshot

echo "Fix broken /var/run link."
  arch-chroot ${ROOT_WORKDIR} echo "After=systemd-tmpfiles-setup.service" >> /usr/lib/systemd/system/network-pre.target

echo "Fix mkinitcpio warning..."
  sed -i '/add_checked_modules_from_symbol.*$/d' ${ROOT_WORKDIR}/usr/lib/initcpio/install/kms

echo "Delete conflicting files..."
# Delete conflicting files
for CONFLICT in etc/X11/Xsession.d/50rotate-screen \
		usr/lib/qt/plugins/discover/steamos-backend.so \
                etc/sddm.conf.d/steamdeck.conf
do
  if [ -e "${ROOT_WORKDIR}/${CONFLICT}" ]
  then
    rm -f "${ROOT_WORKDIR}/${CONFLICT}"
  fi
done

echo "Compile installed package list..."
cat <<EOF >${OUTPUT}/package-versions.txt
Package	Version
EOF
arch-chroot ${ROOT_WORKDIR} pacman -Q >>${OUTPUT}/package-versions.txt

echo "Stop doing things in container..."
# Cleanup
umount -l ${ROOT_WORKDIR}/var/cache/pacman/pkg/

# Finish for now
echo "Packaging snapshot..."
btrfs subvolume snapshot -r ${ROOT_WORKDIR} ${ROOT_WORKDIR}/${OS_FS_PREFIX}_root/rootfs/${BUILDVER}
btrfs send -f ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img ${ROOT_WORKDIR}/${OS_FS_PREFIX}_root/rootfs/${BUILDVER}
umount -l ${ROOT_WORKDIR} && umount -l ${WORKDIR}/work.img && rm -rf ${WORKDIR} && ${WORKDIR}/work.img
if [[ -z "${NO_COMPRESS}" ]]; then
	echo "Compressing image..."
	zstd -z ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img -o ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img.zst
	rm -rf ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img
	chown 1000:1000 ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img.zst
	chmod 777 ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img.zst
fi

if [[ "${IS_HOME_BUILD}" == "true" ]]; then
	cat <<EOF >${OUTPUT}/${FINAL_DISTRIB_IMAGE}.releasemeta
IMAGEFILE="${IMAGEFILE}"
STAGING_OS_TAG=${RELEASE_TAG}
STAGING_RELEASETYPE=$(echo ${OS_CODENAME} | tr '[:upper:]' '[:lower:]')
STAGING_ISINTERNAL=no
EOF
	cp ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.releasemeta ${OUTPUT}/latest_${BUILD_MANIFEST_ID}.releasemeta
	sha256sum ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img.zst | awk '{print $1'} > ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.sha256
	chown 1000:1000 ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.sha256 ${OUTPUT}/latest_${BUILD_MANIFEST_ID}.releasemeta
	chmod 777 ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.sha256 ${OUTPUT}/latest_${BUILD_MANIFEST_ID}.releasemeta
	if [[ -n "${RC_PATH}" ]]; then
		rclone mkdir ${RC_PATH}:/download/$(echo ${OUTPUT} | sed 's#.*steamfork#steamfork#g')
		rclone copy ${OUTPUT}/latest_${BUILD_MANIFEST_ID}.releasemeta ${RC_PATH}:/download/$(echo ${OUTPUT} | sed 's#.*steamfork#steamfork#g') -L --progress
		rclone copy ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.sha256 ${RC_PATH}:/${RC_ROOT}/$(echo ${OUTPUT} | sed 's#.*steamfork#steamfork#g') -L --progress
		rclone copy ${OUTPUT}/${FINAL_DISTRIB_IMAGE}.img.zst ${RC_PATH}:/${RC_ROOT}/$(echo ${OUTPUT} | sed 's#.*steamfork#steamfork#g') -L --progress
	fi
fi

echo "Build complete."
